import type {
  ElementHideType,
  ElementSaveType,
  ElementSelectorCompoundOptions,
  ElementSelectorListenOptions,
} from '../types/constants'
import {
  ELEMENT_HIDE_TYPE,
  ElementConfigSource,
  ElementSelectorDOMScopeType,
  logger,
} from '../types/constants'
import { queryJQuery } from './element_query'
import { ToolKit } from './utils/toolkit'

export interface DynamicHideMetaOption {
  type: ElementSaveType
  domScope: ElementSelectorDOMScopeType
  hostSelector: string
  selector: string
  listenOptions?: ElementSelectorListenOptions
  clearChildStyles?: boolean
  compoundOptions?: ElementSelectorCompoundOptions
  source?: ElementConfigSource
}
export type DynamicHideMetaOptions = Array<DynamicHideMetaOption>

export interface DynamicHideOption {
  interval?: number
  maxCount?: number
  type?: ElementHideType
}

export class DynamicHide {
  private activeOperations: Map<string, AbortController> = new Map()
  private static instance: DynamicHide

  /**
   * 获取单例
   * @returns {ModuleManager} 单例
   */
  public static getInstance(): DynamicHide {
    if (!DynamicHide.instance) {
      DynamicHide.instance = new DynamicHide()
    }
    return DynamicHide.instance
  }

  /**
   * 轮询监听并处理动态元素（支持外部取消）
   * @param selectors 需要监听的选择器数组
   * @param selectors.selector 选择器
   * @param selectors.listenOptions 监听选项
   * @param selectors.clear_child_styles 是否清除子元素样式
   * @param selectors.compoundOptions 复合选择器选项
   * @param options 轮询配置选项
   * @param options.interval 轮询间隔（毫秒）
   * @param options.maxCount 最大轮询次数
   * @param options.type 隐藏类型
   * @returns 取消函数
   */
  pollDynamicHideElements(
    selectors: DynamicHideMetaOptions,
    options: DynamicHideOption = {},
  ): () => void {
    const { interval = 100, maxCount = 30, type = ELEMENT_HIDE_TYPE.ENGINE } = options
    let pollCount = 0 // 轮询计数器
    const abortController = new AbortController()

    // 为每个 selector 注册控制器
    selectors.forEach(({ type, selector, source = ElementConfigSource.System }) => {
      this.activeOperations.set(selector, abortController)
      logger.added(`[${source}] [dynamic] [${type}] ${selector}`)
    })

    const pollHandler = async (): Promise<void> => {
      // 超过最大轮询次数或被取消则停止
      if (abortController.signal.aborted || pollCount >= maxCount) {
        this.cleanupOperations(selectors)
        return
      }

      pollCount++ // 增加计数器

      // 使用微任务拆分工作
      await new Promise<void>((resolve) => {
        requestIdleCallback(
          async (deadline) => {
            try {
              for (const { domScope, hostSelector, selector, listenOptions, clearChildStyles, compoundOptions } of selectors) {
                if (abortController.signal.aborted || !deadline.timeRemaining()) {
                  break
                }

                // 延迟处理
                const $elements = queryJQuery(selector, { domScope, hostSelector })
                if (listenOptions?.timeout && $elements.length !== 0 && $elements.is(':hidden')) {
                  await ToolKit.async.delay(listenOptions.timeout, { signal: abortController.signal })
                }

                await this.processSelectorBatch(
                  selector,
                  abortController.signal,
                  { domScope, hostSelector, clearChildStyles, compoundOptions, type },
                )
              }
            }
            finally {
              resolve()
            }
          },
          { timeout: 50 }, // 确保即使繁忙也会执行
        )
      })

      // 使用 setTimeout 而不是直接递归，避免调用栈堆积
      if (!abortController.signal.aborted && pollCount < maxCount) {
        await new Promise(resolve => setTimeout(resolve, interval))
        await pollHandler()
      }
      else {
        this.cleanupOperations(selectors)
      }
    }

    // 启动轮询
    pollHandler().catch((error) => {
      if (error.name !== 'AbortError') {
        console.error('轮询过程中出错:', error)
      }
      this.cleanupOperations(selectors)
    })

    return () => {
      abortController.abort()
      this.cleanupOperations(selectors)
    }
  }

  /**
   * 取消特定选择器的隐藏处理
   * @param selector 要取消的选择器
   */
  cancelSelectorProcessing(selector: string): void {
    const controller = this.activeOperations.get(selector)
    if (controller) {
      controller.abort()
      this.activeOperations.delete(selector)
      logger.info(`已取消对 ${selector} 的隐藏处理`)
    }
  }

  /**
   * 批量处理选择器元素
   */
  private async processSelectorBatch(
    selector: string,
    signal: AbortSignal,
    options: {
      domScope?: ElementSelectorDOMScopeType
      hostSelector?: string
      clearChildStyles?: boolean
      compoundOptions?: ElementSelectorCompoundOptions
      type?: ElementHideType
    },
  ): Promise<void> {
    // 使用 RAF 确保 DOM 操作在渲染周期执行
    return new Promise<void>((resolve) => {
      requestAnimationFrame(() => {
        if (signal.aborted)
          return resolve()

        const { domScope = ElementSelectorDOMScopeType.Document, hostSelector = '' } = options
        const $elements = queryJQuery(selector, { domScope, hostSelector })
        const batchSize = 50 // 每批处理 50 个元素
        let index = 0

        const processBatch = () => {
          if (signal.aborted)
            return resolve()

          const batchEnd = Math.min(index + batchSize, $elements.length)
          for (; index < batchEnd; index++) {
            if (signal.aborted)
              break

            const el = $elements.eq(index)
            if ($(el).is(':visible')) {
              ToolKit.ui.element.hideElement(selector, options)
            }
          }

          if (index < $elements.length && !signal.aborted) {
            requestAnimationFrame(processBatch)
          }
          else {
            resolve()
          }
        }

        processBatch()
      })
    })
  }

  /**
   * 清理操作记录
   */
  private cleanupOperations(selectors: Array<{ selector: string }>): void {
    selectors.forEach(({ selector }) => {
      this.activeOperations.delete(selector)
    })
  }
}
